home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / OptimizedMesh / OptimizedMesh.cpp next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  41.6 KB  |  978 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: OptimizedMesh.cpp
  3. //
  4. // Starting point for new Direct3D applications
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //--------------------------------------------------------------------------------------
  8. #include "dxstdafx.h"
  9. #include "resource.h"
  10.  
  11. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  12. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  13.  
  14. #define MESHFILENAME L"misc\\knot.x"
  15.  
  16.  
  17. struct SStripData
  18. {
  19.     LPDIRECT3DINDEXBUFFER9  m_pStrips;          // strip indices (single strip)
  20.     LPDIRECT3DINDEXBUFFER9  m_pStripsMany;      // strip indices (many strips)
  21.  
  22.     DWORD                   m_cStripIndices;
  23.     DWORD                  *m_rgcStripLengths;
  24.     DWORD                   m_cStrips;
  25.  
  26.     SStripData() :
  27.         m_pStrips(NULL),
  28.         m_pStripsMany(NULL),
  29.         m_cStripIndices(0),
  30.         m_rgcStripLengths(NULL)
  31.     { }
  32. };
  33.  
  34.  
  35. struct SMeshData
  36. {
  37.     LPD3DXMESH              m_pMeshSysMem;      // System memory copy of mesh
  38.  
  39.     LPD3DXMESH              m_pMesh;            // Local version of mesh, copied on resize
  40.     LPDIRECT3DVERTEXBUFFER9 m_pVertexBuffer;    // vertex buffer of mesh
  41.  
  42.     SStripData             *m_rgStripData;      // strip indices split by attribute
  43.     DWORD                   m_cStripDatas;
  44.  
  45.     SMeshData() :
  46.         m_pMeshSysMem(NULL),
  47.         m_pMesh(NULL),
  48.         m_pVertexBuffer(NULL),
  49.         m_rgStripData(NULL),
  50.         m_cStripDatas(0)
  51.     { }
  52.  
  53.     void ReleaseLocalMeshes()
  54.     {
  55.         SAFE_RELEASE( m_pMesh );
  56.         SAFE_RELEASE( m_pVertexBuffer );
  57.     }
  58.  
  59.     void ReleaseAll()
  60.     {
  61.         SAFE_RELEASE( m_pMeshSysMem );
  62.         SAFE_RELEASE( m_pMesh );
  63.         SAFE_RELEASE( m_pVertexBuffer );
  64.  
  65.         for( DWORD iStripData = 0; iStripData < m_cStripDatas; iStripData++ )
  66.         {
  67.             SAFE_RELEASE( m_rgStripData[iStripData].m_pStrips );
  68.             SAFE_RELEASE( m_rgStripData[iStripData].m_pStripsMany );
  69.             delete[] m_rgStripData[iStripData].m_rgcStripLengths;
  70.         }
  71.  
  72.         delete[] m_rgStripData;
  73.         m_rgStripData = NULL;
  74.         m_cStripDatas = 0;
  75.     }
  76. };
  77.  
  78.  
  79. //--------------------------------------------------------------------------------------
  80. // Global variables
  81. //--------------------------------------------------------------------------------------
  82. ID3DXFont*              g_pFont = NULL;         // Font for drawing text
  83. ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls
  84. ID3DXEffect*            g_pEffect = NULL;       // D3DX effect interface
  85. CModelViewerCamera      g_Camera;               // A model viewing camera
  86. IDirect3DTexture9*      g_pDefaultTex = NULL;   // A default texture
  87. bool                    g_bShowHelp = true;     // If true, it renders the UI control text
  88. CDXUTDialog             g_HUD;                  // dialog for standard controls
  89. CDXUTDialog             g_SampleUI;             // dialog for sample specific controls
  90. bool                    g_bShowVertexCacheOptimized = true; 
  91. bool                    g_bShowStripReordered = false;
  92. bool                    g_bShowStrips = false;
  93. bool                    g_bShowSingleStrip = false;
  94. bool                    g_bForce32ByteFVF = true;
  95. bool                    g_bCantDoSingleStrip = false;// Single strip would be too many primitives
  96. D3DXVECTOR3             g_vObjectCenter;        // Center of bounding sphere of object
  97. FLOAT                   g_fObjectRadius;        // Radius of bounding sphere of object
  98. D3DXMATRIXA16           g_matWorld;
  99. int                     g_cObjectsPerSide = 1;  // sqrt of the number of objects to draw
  100. DWORD                   g_dwMemoryOptions = D3DXMESH_MANAGED;
  101. // various forms of mesh data
  102. SMeshData               g_MeshAttrSorted;
  103. SMeshData               g_MeshStripReordered;
  104. SMeshData               g_MeshVertexCacheOptimized;
  105.  
  106. DWORD                   g_dwNumMaterials = 0;   // Number of materials
  107. IDirect3DTexture9**     g_ppMeshTextures = NULL;
  108. D3DMATERIAL9*           g_pMeshMaterials = NULL;
  109.  
  110.  
  111. //--------------------------------------------------------------------------------------
  112. // UI control IDs
  113. //--------------------------------------------------------------------------------------
  114. #define IDC_TOGGLEFULLSCREEN    1
  115. #define IDC_TOGGLEREF           3
  116. #define IDC_CHANGEDEVICE        4
  117. #define IDC_MESHTYPE            5
  118. #define IDC_GRIDSIZE            6
  119. #define IDC_PRIMTYPE            7
  120.  
  121.  
  122. //--------------------------------------------------------------------------------------
  123. // Forward declarations 
  124. //--------------------------------------------------------------------------------------
  125. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  126. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  127. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  128. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  129. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  130. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  131. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  132. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  133. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  134. void    CALLBACK OnLostDevice();
  135. void    CALLBACK OnDestroyDevice();
  136.  
  137. void    InitApp();
  138. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh );
  139. void    RenderText();
  140. HRESULT LoadMeshData( IDirect3DDevice9 *pd3dDevice, LPCWSTR wszMeshFile, LPD3DXMESH *pMeshSysMemLoaded, LPD3DXBUFFER *ppAdjacencyBuffer );
  141. HRESULT OptimizeMeshData( LPD3DXMESH pMeshSysMem, LPD3DXBUFFER pAdjacencyBuffer, DWORD dwOptFlags, SMeshData *pMeshData );
  142. HRESULT UpdateLocalMeshes( IDirect3DDevice9 *pd3dDevice, SMeshData *pMeshData );
  143. HRESULT DrawMeshData( ID3DXEffect *pEffect, SMeshData *pMeshData );
  144.  
  145.  
  146. //--------------------------------------------------------------------------------------
  147. // Entry point to the program. Initializes everything and goes into a message processing 
  148. // loop. Idle time is used to render the scene.
  149. //--------------------------------------------------------------------------------------
  150. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  151. {
  152.     // Set the callback functions. These functions allow the sample framework to notify
  153.     // the application about device changes, user input, and windows messages.  The 
  154.     // callbacks are optional so you need only set callbacks for events you're interested 
  155.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  156.     // framework won't be able to reset your device since the application must first 
  157.     // release all device resources before resetting.  Likewise, if you don't handle the 
  158.     // device created/destroyed callbacks then the sample framework won't be able to 
  159.     // recreate your device resources.
  160.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  161.     DXUTSetCallbackDeviceReset( OnResetDevice );
  162.     DXUTSetCallbackDeviceLost( OnLostDevice );
  163.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  164.     DXUTSetCallbackMsgProc( MsgProc );
  165.     DXUTSetCallbackKeyboard( KeyboardProc );
  166.     DXUTSetCallbackFrameRender( OnFrameRender );
  167.     DXUTSetCallbackFrameMove( OnFrameMove );
  168.  
  169.     // Show the cursor and clip it when in full screen
  170.     DXUTSetCursorSettings( true, true );
  171.  
  172.     InitApp();
  173.  
  174.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  175.     // device for the application. Calling each of these functions is optional, but they
  176.     // allow you to set several options which control the behavior of the framework.
  177.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  178.     DXUTCreateWindow( L"OptimizedMesh: Optimizing Meshes in D3D" );
  179.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  180.  
  181.     // Pass control to the sample framework for handling the message pump and 
  182.     // dispatching render calls. The sample framework will call your FrameMove 
  183.     // and FrameRender callback when there is idle time between handling window messages.
  184.     DXUTMainLoop();
  185.  
  186.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  187.     // appropriate callback functions and therefore don't require any cleanup code here.
  188.  
  189.     return DXUTGetExitCode();
  190. }
  191.  
  192.  
  193. //--------------------------------------------------------------------------------------
  194. // Initialize the app 
  195. //--------------------------------------------------------------------------------------
  196. void InitApp()
  197. {
  198.     // Initialize dialogs
  199.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  200.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  201.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  202.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  203.  
  204.     g_SampleUI.SetCallback( OnGUIEvent ); iY = 10;
  205.     g_SampleUI.AddComboBox( IDC_MESHTYPE, 0, iY, 200, 20, L'M' );
  206.     g_SampleUI.GetComboBox( IDC_MESHTYPE )->AddItem( L"(M)esh type: VCache optimized", (void*)0 );
  207.     g_SampleUI.GetComboBox( IDC_MESHTYPE )->AddItem( L"(M)esh type: Strip reordered", (void*)1 );
  208.     g_SampleUI.GetComboBox( IDC_MESHTYPE )->AddItem( L"(M)esh type: Unoptimized", (void*)2 );
  209.     g_SampleUI.AddComboBox( IDC_PRIMTYPE, 0, iY += 24, 200, 20, L'P' );
  210.     g_SampleUI.GetComboBox( IDC_PRIMTYPE )->AddItem( L"(P)rimitive: Triangle list", (void*)0 );
  211.     g_SampleUI.GetComboBox( IDC_PRIMTYPE )->AddItem( L"(P)rimitive: Single tri strip", (void*)0 );
  212.     g_SampleUI.GetComboBox( IDC_PRIMTYPE )->AddItem( L"(P)rimitive: Many tri strips", (void*)0 );
  213.     g_SampleUI.AddComboBox( IDC_GRIDSIZE, 0, iY += 24, 200, 20, L'G' );
  214.     g_SampleUI.GetComboBox( IDC_GRIDSIZE )->AddItem( L"(G)rid size: 1 mesh", (void*)1 );
  215.     g_SampleUI.GetComboBox( IDC_GRIDSIZE )->AddItem( L"(G)rid size: 4 mesh", (void*)2 );
  216.     g_SampleUI.GetComboBox( IDC_GRIDSIZE )->AddItem( L"(G)rid size: 9 mesh", (void*)3 );
  217.     g_SampleUI.GetComboBox( IDC_GRIDSIZE )->AddItem( L"(G)rid size: 16 mesh", (void*)4 );
  218.     g_SampleUI.GetComboBox( IDC_GRIDSIZE )->AddItem( L"(G)rid size: 25 mesh", (void*)5 );
  219.     g_SampleUI.GetComboBox( IDC_GRIDSIZE )->AddItem( L"(G)rid size: 36 mesh", (void*)6 );
  220.  
  221.     g_Camera.SetButtonMasks( MOUSE_LEFT_BUTTON, MOUSE_WHEEL, 0 );
  222. }
  223.  
  224.  
  225. //--------------------------------------------------------------------------------------
  226. // Called during device initialization, this code checks the device for some 
  227. // minimum set of capabilities, and rejects those that don't pass by returning false.
  228. //--------------------------------------------------------------------------------------
  229. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  230.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  231. {
  232.     // Skip backbuffer formats that don't support alpha blending
  233.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  234.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  235.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  236.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  237.         return false;
  238.  
  239.     return true;
  240. }
  241.  
  242.  
  243. //--------------------------------------------------------------------------------------
  244. // This callback function is called immediately before a device is created to allow the 
  245. // application to modify the device settings. The supplied pDeviceSettings parameter 
  246. // contains the settings that the framework has selected for the new device, and the 
  247. // application can make any desired changes directly to this structure.  Note however that 
  248. // the sample framework will not correct invalid device settings so care must be taken 
  249. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  250. //--------------------------------------------------------------------------------------
  251. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  252. {
  253.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  254.     // then switch to SWVP.
  255.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  256.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  257.     {
  258.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  259.     }
  260.     else
  261.     {
  262.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  263.     }
  264.  
  265.     // This application is designed to work on a pure device by not using 
  266.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  267.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  268.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  269.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  270.  
  271.     // Debugging vertex shaders requires either REF or software vertex processing 
  272.     // and debugging pixel shaders requires REF.  
  273. #ifdef DEBUG_VS
  274.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  275.     {
  276.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  277.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;                            
  278.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  279.     }
  280. #endif
  281. #ifdef DEBUG_PS
  282.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  283. #endif
  284. }
  285.  
  286.  
  287. HRESULT LoadMeshData( IDirect3DDevice9 *pd3dDevice, LPCWSTR wszMeshFile, LPD3DXMESH *pMeshSysMemLoaded, LPD3DXBUFFER *ppAdjacencyBuffer )
  288. {
  289.     LPDIRECT3DVERTEXBUFFER9 pMeshVB = NULL;
  290.     LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
  291.     void*        pVertices;
  292.     WCHAR        strMesh[512];
  293.     HRESULT      hr = S_OK;
  294.     LPD3DXMESH   pMeshSysMem = NULL;
  295.     LPD3DXMESH   pMeshTemp;
  296.     D3DXMATERIAL* d3dxMaterials;
  297.  
  298.     // Get a path to the media file
  299.     if( FAILED( hr = DXUTFindDXSDKMediaFileCch( strMesh, 512, wszMeshFile ) ) )
  300.         goto End;
  301.  
  302.     // Load the mesh from the specified file
  303.     hr = D3DXLoadMeshFromX( strMesh, D3DXMESH_SYSTEMMEM, pd3dDevice, 
  304.                             ppAdjacencyBuffer, &pD3DXMtrlBuffer, NULL,
  305.                             &g_dwNumMaterials, &pMeshSysMem );
  306.     if( FAILED(hr) )
  307.         goto End;
  308.  
  309.     // Get the array of materials out of the returned buffer, and allocate a texture array
  310.     d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
  311.     g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials];
  312.     if( g_pMeshMaterials == NULL )
  313.     {
  314.         hr = E_OUTOFMEMORY;
  315.         goto End;
  316.     }
  317.     g_ppMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials];
  318.     if( g_ppMeshTextures == NULL )
  319.     {
  320.         hr = E_OUTOFMEMORY;
  321.         goto End;
  322.     }
  323.  
  324.     for( DWORD i = 0; i < g_dwNumMaterials; i++ )
  325.     {
  326.         g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
  327.         g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;
  328.         g_ppMeshTextures[i]  = NULL;
  329.  
  330.         // Get a path to the texture
  331.         WCHAR strPath[512];
  332.         if( d3dxMaterials[i].pTextureFilename != NULL )
  333.         {
  334.             WCHAR wszBuf[MAX_PATH];
  335.             MultiByteToWideChar( CP_ACP, 0, d3dxMaterials[i].pTextureFilename, -1, wszBuf, MAX_PATH );
  336.             wszBuf[MAX_PATH - 1] = L'\0';
  337.             DXUTFindDXSDKMediaFileCch( strPath, 512, wszBuf );
  338.  
  339.             // Load the texture
  340.             D3DXCreateTextureFromFile( pd3dDevice, strPath, &g_ppMeshTextures[i] );
  341.         } else
  342.         {
  343.             // Use the default texture
  344.             g_ppMeshTextures[i] = g_pDefaultTex;
  345.             g_ppMeshTextures[i]->AddRef();
  346.         }
  347.     }
  348.  
  349.     // Done with the material buffer
  350.     SAFE_RELEASE( pD3DXMtrlBuffer );
  351.  
  352.     // Lock the vertex buffer, to generate a simple bounding sphere
  353.     hr = pMeshSysMem->GetVertexBuffer( &pMeshVB );
  354.     if( SUCCEEDED(hr) )
  355.     {
  356.         hr = pMeshVB->Lock( 0, 0, &pVertices, D3DLOCK_NOSYSLOCK );
  357.         if( SUCCEEDED(hr) )
  358.         {
  359.             D3DXComputeBoundingSphere( (D3DXVECTOR3*)pVertices, pMeshSysMem->GetNumVertices(),
  360.                                        D3DXGetFVFVertexSize( pMeshSysMem->GetFVF() ),
  361.                                        &g_vObjectCenter, &g_fObjectRadius );
  362.             pMeshVB->Unlock();
  363.         }
  364.         pMeshVB->Release();
  365.     } else
  366.         goto End;
  367.  
  368.     // remember if there were normals in the file, before possible clone operation
  369.     bool bNormalsInFile = ( pMeshSysMem->GetFVF() & D3DFVF_NORMAL ) != 0;
  370.  
  371.     // if using 32byte vertices, check fvf
  372.     if( g_bForce32ByteFVF )
  373.     {
  374.         // force 32 byte vertices
  375.         if( pMeshSysMem->GetFVF() != (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1) )
  376.         {
  377.             hr = pMeshSysMem->CloneMeshFVF( pMeshSysMem->GetOptions(), D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, 
  378.                                             pd3dDevice, &pMeshTemp );
  379.             if( FAILED(hr) )
  380.                 goto End;
  381.  
  382.             pMeshSysMem->Release();
  383.             pMeshSysMem = pMeshTemp;
  384.         }
  385.     }
  386.     // otherwise, just make sure that there are normals in mesh
  387.     else if ( !(pMeshSysMem->GetFVF() & D3DFVF_NORMAL) )
  388.     {
  389.         hr = pMeshSysMem->CloneMeshFVF( pMeshSysMem->GetOptions(), pMeshSysMem->GetFVF() | D3DFVF_NORMAL, 
  390.                                         pd3dDevice, &pMeshTemp );
  391.         if (FAILED(hr))
  392.             goto End;
  393.  
  394.         pMeshSysMem->Release();
  395.         pMeshSysMem = pMeshTemp;
  396.     }
  397.  
  398.     // Compute normals for the mesh, if not present
  399.     if( !bNormalsInFile )
  400.         D3DXComputeNormals( pMeshSysMem, NULL );
  401.  
  402.     *pMeshSysMemLoaded = pMeshSysMem;
  403.     pMeshSysMem = NULL;
  404.  
  405. End:
  406.     SAFE_RELEASE( pMeshSysMem );
  407.  
  408.     return hr;
  409. }
  410.  
  411.  
  412. HRESULT OptimizeMeshData( LPD3DXMESH pMeshSysMem, LPD3DXBUFFER pAdjacencyBuffer, DWORD dwOptFlags, SMeshData *pMeshData )
  413. {
  414.     HRESULT hr = S_OK;
  415.     LPD3DXBUFFER pbufTemp = NULL;
  416.  
  417.     // Attribute sort - the un-optimized mesh option
  418.     // remember the adjacency for the vertex cache optimization
  419.     hr = pMeshSysMem->Optimize( dwOptFlags | D3DXMESH_SYSTEMMEM,
  420.                                  (DWORD*)pAdjacencyBuffer->GetBufferPointer(),
  421.                                  NULL, NULL, NULL, &pMeshData->m_pMeshSysMem );
  422.     if( FAILED(hr) )
  423.         goto End;
  424.  
  425.     pMeshData->m_cStripDatas = g_dwNumMaterials;
  426.     pMeshData->m_rgStripData = new SStripData[ pMeshData->m_cStripDatas ];
  427.     if( pMeshData->m_rgStripData == NULL )
  428.     {
  429.         hr = E_OUTOFMEMORY;
  430.         goto End;
  431.     }
  432.  
  433.     g_bCantDoSingleStrip = false;
  434.     for( DWORD iMaterial = 0; iMaterial < g_dwNumMaterials; iMaterial++ )
  435.     {
  436.         hr = D3DXConvertMeshSubsetToSingleStrip( pMeshData->m_pMeshSysMem, iMaterial,
  437.                                 D3DXMESH_IB_MANAGED, &pMeshData->m_rgStripData[iMaterial].m_pStrips,
  438.                                 &pMeshData->m_rgStripData[iMaterial].m_cStripIndices);
  439.         if( FAILED(hr) )
  440.             goto End;
  441.  
  442.         UINT primCount = pMeshData->m_rgStripData[iMaterial].m_cStripIndices - 2;
  443.  
  444.         IDirect3DDevice9 *pd3dDevice;
  445.         D3DCAPS9 d3dCaps;
  446.         pMeshSysMem->GetDevice( &pd3dDevice );
  447.         pd3dDevice->GetDeviceCaps( &d3dCaps );
  448.         SAFE_RELEASE( pd3dDevice );
  449.         if( primCount > d3dCaps.MaxPrimitiveCount )
  450.         {
  451.             g_bCantDoSingleStrip = true;
  452.         }
  453.  
  454.         hr = D3DXConvertMeshSubsetToStrips( pMeshData->m_pMeshSysMem, iMaterial, 
  455.                                 D3DXMESH_IB_MANAGED, &pMeshData->m_rgStripData[iMaterial].m_pStripsMany, 
  456.                                 NULL, &pbufTemp, &pMeshData->m_rgStripData[iMaterial].m_cStrips);
  457.         if( FAILED(hr) )
  458.             goto End;
  459.  
  460.         pMeshData->m_rgStripData[iMaterial].m_rgcStripLengths = new DWORD[pMeshData->m_rgStripData[iMaterial].m_cStrips];
  461.         if( pMeshData->m_rgStripData[iMaterial].m_rgcStripLengths == NULL )
  462.         {
  463.             hr = E_OUTOFMEMORY;
  464.             goto End;
  465.         }
  466.         memcpy( pMeshData->m_rgStripData[iMaterial].m_rgcStripLengths,
  467.                 pbufTemp->GetBufferPointer(),
  468.                 sizeof(DWORD) * pMeshData->m_rgStripData[iMaterial].m_cStrips );
  469.     }
  470.  
  471. End:
  472.     SAFE_RELEASE( pbufTemp );
  473.  
  474.     return hr;
  475. }
  476.  
  477.  
  478. HRESULT UpdateLocalMeshes( IDirect3DDevice9 *pd3dDevice, SMeshData *pMeshData )
  479. {
  480.     HRESULT hr = S_OK;
  481.  
  482.     // if a mesh was loaded, update the local meshes
  483.     if( pMeshData->m_pMeshSysMem != NULL )
  484.     {
  485.         hr = pMeshData->m_pMeshSysMem->CloneMeshFVF( g_dwMemoryOptions | D3DXMESH_VB_WRITEONLY, pMeshData->m_pMeshSysMem->GetFVF(),
  486.                                           pd3dDevice, &pMeshData->m_pMesh );
  487.         if( FAILED(hr) )
  488.             return hr;
  489.  
  490.         hr = pMeshData->m_pMesh->GetVertexBuffer( &pMeshData->m_pVertexBuffer );
  491.         if( FAILED(hr) )
  492.             return hr;
  493.     }
  494.  
  495.     return hr;
  496. }
  497.  
  498.  
  499. HRESULT DrawMeshData( IDirect3DDevice9 *pd3dDevice, ID3DXEffect *pEffect, SMeshData *pMeshData )
  500. {
  501.     HRESULT hr;
  502.     DWORD iCurFace;
  503.  
  504.     V( pEffect->SetTechnique( "RenderScene" ) );
  505.     UINT cPasses;
  506.     V( pEffect->Begin( &cPasses, 0 ) );
  507.     for( UINT p = 0; p < cPasses; ++p )
  508.     {
  509.         V( pEffect->BeginPass( p ) );
  510.  
  511.         // Set and draw each of the materials in the mesh
  512.         for( DWORD iMaterial = 0; iMaterial < g_dwNumMaterials; iMaterial++ )
  513.         {
  514.             V( pEffect->SetVector( "g_vDiffuse", (D3DXVECTOR4*)&g_pMeshMaterials[iMaterial].Diffuse ) );
  515.             V( pEffect->SetTexture( "g_txScene", g_ppMeshTextures[iMaterial] ) );
  516.             V( pEffect->CommitChanges() );
  517. //            V( pd3dDevice->SetMaterial( &g_pMeshMaterials[iMaterial] ) );
  518. //            V( pd3dDevice->SetTexture( 0, g_ppMeshTextures[iMaterial] ) );
  519.  
  520.             if( !g_bShowStrips && !g_bShowSingleStrip )
  521.             {
  522.                 V( pMeshData->m_pMesh->DrawSubset( iMaterial ) );
  523.             }
  524.             else  // drawing strips
  525.             {
  526.                 DWORD dwFVF;
  527.                 DWORD cBytesPerVertex;
  528.                 DWORD iStrip;
  529.  
  530.                 dwFVF = pMeshData->m_pMesh->GetFVF();
  531.                 cBytesPerVertex = D3DXGetFVFVertexSize( dwFVF );
  532.  
  533.                 V( pd3dDevice->SetFVF( dwFVF ) );
  534.                 V( pd3dDevice->SetStreamSource( 0, pMeshData->m_pVertexBuffer, 0, cBytesPerVertex ) );
  535.  
  536.                 if( g_bShowSingleStrip )
  537.                 {
  538.                     if( !g_bCantDoSingleStrip )
  539.                     {
  540.                         V( pd3dDevice->SetIndices( pMeshData->m_rgStripData[iMaterial].m_pStrips ) );
  541.  
  542.                         V( pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0,
  543.                                                     0, pMeshData->m_pMesh->GetNumVertices(),
  544.                                                     0, pMeshData->m_rgStripData[iMaterial].m_cStripIndices - 2 ) );
  545.                     }
  546.                 }
  547.                 else
  548.                 {
  549.                     V( pd3dDevice->SetIndices( pMeshData->m_rgStripData[iMaterial].m_pStripsMany ) );
  550.  
  551.                     iCurFace = 0;
  552.                     for( iStrip = 0; iStrip < pMeshData->m_rgStripData[iMaterial].m_cStrips; iStrip++ )
  553.                     {
  554.                         V( pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0,
  555.                                                     0, pMeshData->m_pMesh->GetNumVertices(),
  556.                                                     iCurFace, pMeshData->m_rgStripData[iMaterial].m_rgcStripLengths[iStrip] ) );
  557.  
  558.                         iCurFace += 2 + pMeshData->m_rgStripData[iMaterial].m_rgcStripLengths[iStrip];
  559.                     }
  560.                 }
  561.             }
  562.         }
  563.         V( pEffect->EndPass() );
  564.     }
  565.     V( pEffect->End() );
  566.  
  567.     return S_OK;
  568. }
  569.  
  570.  
  571. //--------------------------------------------------------------------------------------
  572. // This callback function will be called immediately after the Direct3D device has been 
  573. // created, which will happen during application initialization and windowed/full screen 
  574. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  575. // resources need to be reloaded whenever the device is destroyed. Resources created  
  576. // here should be released in the OnDestroyDevice callback. 
  577. //--------------------------------------------------------------------------------------
  578. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  579. {
  580.     HRESULT hr;
  581.  
  582.     // Create the 1x1 white default texture
  583.     V_RETURN( pd3dDevice->CreateTexture( 1, 1, 1, 0, D3DFMT_A8R8G8B8,
  584.                                          D3DPOOL_MANAGED, &g_pDefaultTex, NULL ) );
  585.     D3DLOCKED_RECT lr;
  586.     V_RETURN( g_pDefaultTex->LockRect( 0, &lr, NULL, 0 ) );
  587.     *(LPDWORD)lr.pBits = D3DCOLOR_RGBA( 255, 255, 255, 255 );
  588.     V_RETURN( g_pDefaultTex->UnlockRect( 0 ) );
  589.  
  590.     // Initialize the font
  591.     V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  592.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  593.                          L"Arial", &g_pFont ) );
  594.  
  595.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  596.     // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  597.     // processing, and debugging pixel shaders requires REF.  The 
  598.     // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
  599.     // shader debugger.  It enables source level debugging, prevents instruction 
  600.     // reordering, prevents dead code elimination, and forces the compiler to compile 
  601.     // against the next higher available software target, which ensures that the 
  602.     // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  603.     // flags will cause slower rendering since the shaders will be unoptimized and 
  604.     // forced into software.  See the DirectX documentation for more information about 
  605.     // using the shader debugger.
  606.     DWORD dwShaderFlags = 0;
  607.     #ifdef DEBUG_VS
  608.         dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  609.     #endif
  610.     #ifdef DEBUG_PS
  611.         dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  612.     #endif
  613.  
  614.     // Read the D3DX effect file
  615.     WCHAR str[MAX_PATH];
  616.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"OptimizedMesh.fx" ) );
  617.  
  618.     // If this fails, there should be debug output as to 
  619.     // they the .fx file failed to compile
  620.     V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, 
  621.                                         NULL, &g_pEffect, NULL ) );
  622.  
  623.     // Load mesh
  624.     LPD3DXMESH   pMeshSysMem = NULL;
  625.     LPD3DXBUFFER pAdjacencyBuffer = NULL;
  626.  
  627.     hr = LoadMeshData( pd3dDevice, MESHFILENAME, &pMeshSysMem, &pAdjacencyBuffer );
  628.     if( SUCCEEDED(hr) )
  629.     {
  630.         hr = OptimizeMeshData( pMeshSysMem, pAdjacencyBuffer, D3DXMESHOPT_ATTRSORT, &g_MeshAttrSorted );
  631.         if( SUCCEEDED(hr) )
  632.             hr = OptimizeMeshData( pMeshSysMem, pAdjacencyBuffer, D3DXMESHOPT_STRIPREORDER, &g_MeshStripReordered );
  633.  
  634.         if( SUCCEEDED(hr) )
  635.             hr = OptimizeMeshData( pMeshSysMem, pAdjacencyBuffer, D3DXMESHOPT_VERTEXCACHE, &g_MeshVertexCacheOptimized );
  636.  
  637.         SAFE_RELEASE( pMeshSysMem );
  638.         SAFE_RELEASE( pAdjacencyBuffer );
  639.     } else
  640.         // ignore load errors, just draw blank screen if mesh is invalid
  641.         hr = S_OK;
  642.  
  643.     D3DXMatrixTranslation( &g_matWorld, -g_vObjectCenter.x,
  644.                                         -g_vObjectCenter.y,
  645.                                         -g_vObjectCenter.z );
  646.  
  647.     // Setup the camera's view parameters
  648.     D3DXVECTOR3 vecEye(0.0f, 0.0f, -5.0f);
  649.     D3DXVECTOR3 vecAt (0.0f, 0.0f, -0.0f);
  650.     g_Camera.SetViewParams( &vecEye, &vecAt );
  651.  
  652.     return S_OK;
  653. }
  654.  
  655.  
  656. //--------------------------------------------------------------------------------------
  657. // This callback function will be called immediately after the Direct3D device has been 
  658. // reset, which will happen after a lost device scenario. This is the best location to 
  659. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  660. // the device is lost. Resources created here should be released in the OnLostDevice 
  661. // callback. 
  662. //--------------------------------------------------------------------------------------
  663. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  664.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  665. {
  666.     HRESULT hr;
  667.  
  668.     if( g_pFont )
  669.         V_RETURN( g_pFont->OnResetDevice() );
  670.     if( g_pEffect )
  671.         V_RETURN( g_pEffect->OnResetDevice() );
  672.  
  673.     // Create a sprite to help batch calls when drawing many lines of text
  674.     V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
  675.  
  676.     // Setup the camera's projection parameters
  677.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  678.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
  679.     g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  680.  
  681.     // update the local copies of the meshes
  682.     UpdateLocalMeshes( pd3dDevice, &g_MeshAttrSorted );
  683.     UpdateLocalMeshes( pd3dDevice, &g_MeshStripReordered );
  684.     UpdateLocalMeshes( pd3dDevice, &g_MeshVertexCacheOptimized );
  685.  
  686.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  687.     g_HUD.SetSize( 170, 170 );
  688.     g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width-200, pBackBufferSurfaceDesc->Height-350 );
  689.     g_SampleUI.SetSize( 200, 300 );
  690.  
  691.     return S_OK;
  692. }
  693.  
  694.  
  695. //--------------------------------------------------------------------------------------
  696. // This callback function will be called once at the beginning of every frame. This is the
  697. // best location for your application to handle updates to the scene, but is not 
  698. // intended to contain actual rendering calls, which should instead be placed in the 
  699. // OnFrameRender callback.  
  700. //--------------------------------------------------------------------------------------
  701. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  702. {
  703.     // Update the camera's position based on user input 
  704.     g_Camera.FrameMove( fElapsedTime );
  705. }
  706.  
  707.  
  708. //--------------------------------------------------------------------------------------
  709. // This callback function will be called at the end of every frame to perform all the 
  710. // rendering calls for the scene, and it will also be called if the window needs to be 
  711. // repainted. After this function has returned, the sample framework will call 
  712. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  713. //--------------------------------------------------------------------------------------
  714. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  715. {
  716.     HRESULT hr;
  717.     D3DXMATRIXA16 mWorld;
  718.     D3DXMATRIXA16 mView;
  719.     D3DXMATRIXA16 mProj;
  720.     D3DXMATRIXA16 mWorldViewProjection;
  721.     
  722.     // Clear the render target and the zbuffer 
  723.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 66, 75, 121), 1.0f, 0) );
  724.  
  725.     // Render the scene
  726.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  727.     {
  728.         // Get the projection & view matrix from the camera class
  729. //        mWorld = *g_Camera.GetWorldMatrix();
  730.         mProj = *g_Camera.GetProjMatrix();
  731.         mView = *g_Camera.GetViewMatrix();
  732.  
  733.         DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"Draw mesh" );
  734.  
  735.         for( int xOffset = 0; xOffset < g_cObjectsPerSide; xOffset++ )
  736.         {
  737.             for( int yOffset = 0; yOffset < g_cObjectsPerSide; yOffset++ )
  738.             {
  739.                 D3DXMatrixTranslation( &mWorld, g_fObjectRadius * ( xOffset * 2 - g_cObjectsPerSide + 1 ),
  740.                                                 g_fObjectRadius * ( yOffset * 2 - g_cObjectsPerSide + 1 ),
  741.                                                 0 );
  742.                 D3DXMatrixMultiply( &mWorld, g_Camera.GetWorldMatrix(), &mWorld );
  743.                 D3DXMatrixMultiply( &mWorld, &g_matWorld, &mWorld );
  744.  
  745.                 mWorldViewProjection = mWorld * mView * mProj;
  746.                 // Update the effect's variables.  Instead of using strings, it would 
  747.                 // be more efficient to cache a handle to the parameter by calling 
  748.                 // ID3DXEffect::GetParameterByName
  749.                 V( g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) );
  750.                 V( g_pEffect->SetMatrix( "g_mWorld", &mWorld ) );
  751.  
  752.                 if( g_bShowVertexCacheOptimized )
  753.                     DrawMeshData( pd3dDevice, g_pEffect, &g_MeshVertexCacheOptimized );
  754.                 else if( g_bShowStripReordered )
  755.                     DrawMeshData( pd3dDevice, g_pEffect, &g_MeshStripReordered );
  756.                 else
  757.                     DrawMeshData( pd3dDevice, g_pEffect, &g_MeshAttrSorted );
  758.             }
  759.         }
  760.  
  761.         DXUT_EndPerfEvent(); // end of drawing code
  762.  
  763.         {
  764.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"HUD / Stats" );
  765.             RenderText();
  766.             V( g_HUD.OnRender( fElapsedTime ) );
  767.             V( g_SampleUI.OnRender( fElapsedTime ) );
  768.         }
  769.             
  770.         V( pd3dDevice->EndScene() );
  771.     }
  772. }
  773.  
  774.  
  775. //--------------------------------------------------------------------------------------
  776. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  777. // efficient text rendering.
  778. //--------------------------------------------------------------------------------------
  779. void RenderText()
  780. {
  781.     // The helper object simply helps keep track of text position, and color
  782.     // and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
  783.     // If NULL is passed in as the sprite object, then it will work however the 
  784.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  785.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  786.  
  787.     WCHAR *wszOptString;
  788.     DWORD cTriangles = 0;
  789.     // Calculate and show triangles per sec, a reasonable throughput number
  790.     if( g_MeshAttrSorted.m_pMesh != NULL )
  791.         cTriangles = g_MeshAttrSorted.m_pMesh->GetNumFaces() * g_cObjectsPerSide * g_cObjectsPerSide;
  792.     else
  793.         cTriangles = 0;
  794.  
  795.     float fTrisPerSec = DXUTGetFPS() * cTriangles;
  796.  
  797.     if( g_bShowVertexCacheOptimized )
  798.         wszOptString = L"VCache Optimized";
  799.     else if( g_bShowStripReordered )
  800.         wszOptString = L"Strip Reordered";
  801.     else
  802.         wszOptString = L"Unoptimized";
  803.  
  804.     // Output statistics
  805.     txtHelper.Begin();
  806.     txtHelper.SetInsertionPos( 5, 5 );
  807.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  808.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  809.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  810.     txtHelper.DrawFormattedTextLine( L"%s, %ld tris per sec, %ld triangles",
  811.                                      wszOptString, (DWORD)fTrisPerSec, cTriangles );
  812.  
  813.     if( g_bShowSingleStrip && g_bCantDoSingleStrip )
  814.         txtHelper.DrawTextLine( L"Couldn't draw to single strip -- too many primitives" );
  815.  
  816.     // Draw help
  817.     if( g_bShowHelp )
  818.     {
  819.         const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  820.         txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*6 );
  821.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
  822.         txtHelper.DrawTextLine( L"Controls (F1 to hide):" );
  823.  
  824.         txtHelper.SetInsertionPos( 40, pd3dsdBackBuffer->Height-15*5 );
  825.         txtHelper.DrawTextLine( L"Rotate mesh: Left click drag\n"
  826.                                 L"Zoom: mouse wheel\n"
  827.                                 L"Quit: ESC" );
  828.     }
  829.     else
  830.     {
  831.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  832.         txtHelper.DrawTextLine( L"Press F1 for help" );
  833.     }
  834.     txtHelper.End();
  835. }
  836.  
  837.  
  838. //--------------------------------------------------------------------------------------
  839. // Before handling window messages, the sample framework passes incoming windows 
  840. // messages to the application through this callback function. If the application sets 
  841. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  842. //--------------------------------------------------------------------------------------
  843. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  844. {
  845.     // Give the dialogs a chance to handle the message first
  846.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  847.     if( *pbNoFurtherProcessing )
  848.         return 0;
  849.     *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
  850.     if( *pbNoFurtherProcessing )
  851.         return 0;
  852.  
  853.     // Pass all remaining windows messages to camera so it can respond to user input
  854.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  855.  
  856.     return 0;
  857. }
  858.  
  859.  
  860. //--------------------------------------------------------------------------------------
  861. // As a convenience, the sample framework inspects the incoming windows messages for
  862. // keystroke messages and decodes the message parameters to pass relevant keyboard
  863. // messages to the application.  The framework does not remove the underlying keystroke 
  864. // messages, which are still passed to the application's MsgProc callback.
  865. //--------------------------------------------------------------------------------------
  866. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  867. {
  868.     if( bKeyDown )
  869.     {
  870.         switch( nChar )
  871.         {
  872.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  873.         }
  874.     }
  875. }
  876.  
  877.  
  878. //--------------------------------------------------------------------------------------
  879. // Handles the GUI events
  880. //--------------------------------------------------------------------------------------
  881. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  882. {
  883.     switch( nControlID )
  884.     {
  885.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  886.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  887.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  888.         case IDC_MESHTYPE:
  889.             switch( (size_t)((CDXUTComboBox*)pControl)->GetSelectedData() )
  890.             {
  891.                 case 0:
  892.                     g_bShowVertexCacheOptimized = true;
  893.                     g_bShowStripReordered = false;
  894.                     break;
  895.                 case 1:
  896.                     g_bShowVertexCacheOptimized = false;
  897.                     g_bShowStripReordered = true;
  898.                     break;
  899.                 case 2:
  900.                     g_bShowVertexCacheOptimized = false;
  901.                     g_bShowStripReordered = false;
  902.                     break;
  903.             }
  904.             break;
  905.  
  906.         case IDC_PRIMTYPE:
  907.             switch( (size_t)((CDXUTComboBox*)pControl)->GetSelectedData() )
  908.             {
  909.                 case 0:
  910.                     g_bShowStrips = false;
  911.                     g_bShowSingleStrip = false;
  912.                     break;
  913.                 case 1:
  914.                     g_bShowStrips = false;
  915.                     g_bShowSingleStrip = true;
  916.                     break;
  917.                 case 2:
  918.                     g_bShowStrips = true;
  919.                     g_bShowSingleStrip = false;
  920.                     break;
  921.             }
  922.             break;
  923.  
  924.         case IDC_GRIDSIZE:
  925.             g_cObjectsPerSide = (int)(size_t)((CDXUTComboBox*)pControl)->GetSelectedData();
  926.             break;
  927.     }
  928. }
  929.  
  930.  
  931. //--------------------------------------------------------------------------------------
  932. // This callback function will be called immediately after the Direct3D device has 
  933. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  934. // in the OnResetDevice callback should be released here, which generally includes all 
  935. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  936. // information about lost devices.
  937. //--------------------------------------------------------------------------------------
  938. void CALLBACK OnLostDevice()
  939. {
  940.     if( g_pFont )
  941.         g_pFont->OnLostDevice();
  942.     if( g_pEffect )
  943.         g_pEffect->OnLostDevice();
  944.     SAFE_RELEASE( g_pTextSprite );
  945.  
  946.     g_MeshAttrSorted.ReleaseLocalMeshes();
  947.     g_MeshStripReordered.ReleaseLocalMeshes();
  948.     g_MeshVertexCacheOptimized.ReleaseLocalMeshes();
  949. }
  950.  
  951.  
  952. //--------------------------------------------------------------------------------------
  953. // This callback function will be called immediately after the Direct3D device has 
  954. // been destroyed, which generally happens as a result of application termination or 
  955. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  956. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  957. //--------------------------------------------------------------------------------------
  958. void CALLBACK OnDestroyDevice()
  959. {
  960.     SAFE_RELEASE(g_pEffect);
  961.     SAFE_RELEASE(g_pFont);
  962.  
  963.     for( UINT i = 0; i<g_dwNumMaterials; i++ )
  964.         SAFE_RELEASE( g_ppMeshTextures[i] );
  965.     SAFE_DELETE_ARRAY( g_ppMeshTextures );
  966.     SAFE_DELETE_ARRAY( g_pMeshMaterials );
  967.     SAFE_RELEASE( g_pDefaultTex );
  968.  
  969.     g_MeshAttrSorted.ReleaseAll();
  970.     g_MeshStripReordered.ReleaseAll();
  971.     g_MeshVertexCacheOptimized.ReleaseAll();
  972.  
  973.     g_dwNumMaterials = 0;
  974. }
  975.  
  976.  
  977.  
  978.